﻿using System;
using System.Collections.Generic;

using System.Text;
using System.Reflection;
using System.CodeDom.Compiler;

namespace Flame.Dlr
{
    /// <summary>
    /// You can compile c# code to add functionalities to others scripting languages
    /// it compiles a class into an assembly and add this assembly to other scope
    /// </summary>
    /// 
    public class CSharpCompiler : CodeDomCompiler
    {

        public CSharpCompiler(/*IEnumerable<IExecutable> execs*/)
            //: base(execs)
        {
        }

        public override CodeDomProvider CodeDomProvider { get { return new Microsoft.CSharp.CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v4.0" } }); } }
    }

    /*public class CSharpCompiler : ICompiler
    {
        public class Result
        {
            public ResultAssembly ResultAssembly { get; set; }
            public ICompiler Compiler { get; set; }
        }

        ICompiler[] _compilers;
        List<AssemblyWrapper> _assembliesToLoad = new List<AssemblyWrapper>();



        public CSharpCompiler(IEnumerable<ICompiler> compilers)
        {
            var lcompilers = compilers.ToList < ICompiler>();
            lcompilers.Add(this);
            _compilers = lcompilers.ToArray();
           // _persitentVariables = vars;
        }

        public CompilerResult Compile(string script) 
        {
            using (Microsoft.CSharp.CSharpCodeProvider foo = new Microsoft.CSharp.CSharpCodeProvider(new Dictionary<String, String> { { "CompilerVersion", "v4.0" } }))
            {
                try
                {

                    var parameters = new System.CodeDom.Compiler.CompilerParameters();
                    parameters.GenerateInMemory = false;
                    parameters.GenerateExecutable = false;
                    parameters.IncludeDebugInformation = false;

                    foreach (AssemblyWrapper assembly in _assembliesToLoad)
                    {
                        try
                        {
                            parameters.ReferencedAssemblies.Add(assembly.Location);
                        }
                        catch
                        {
                        }
                    }

                    try
                    {
                        var res = foo.CompileAssemblyFromSource(parameters, script);
                        if (res.Errors.HasErrors)
                            return new CompilerResult() { Data = res.Errors[0] };


                        foo.Dispose();

                        List<Result> errors = new List<Result>();
                        foreach (ICompiler c in _compilers)
                        {
                            var resultAssembly = c.AddAssembly(new AssemblyWrapper(res.CompiledAssembly));
                            if (resultAssembly != null && resultAssembly.Exception != null)
                                errors.Add(new Result() { ResultAssembly = resultAssembly, Compiler = c });
                        }
                        if (errors.Count != 0) return new CompilerResult() { Data = errors };
                        return new CompilerResult() { Data = true };
                    }
                    catch (Exception e)
                    {
                        return new CompilerResult() { Data = e };
                    }
                }
                catch (System.Exception e)
                {
                    return new CompilerResult() { Data = e };
                }
            }
        }
        
        public void AddVariable(Variable variable) { }
        public void ClearScope() { }
        public Languages Language { get { return Languages.CSharp; } }

        public ResultAssembly AddAssembly(AssemblyWrapper ainfo)
        {
            _assembliesToLoad.Add(ainfo);
            return new ResultAssembly() { Loaded = false, Exception = null, Language = Language };
        }

    }*/
}
